-- =================== Model ======================
Model = {
    index = 1,
    dataset = {
        {name='! menu 1', enable=false},
        {name='! menu 2', enable=false},
        {name='! menu 3', enable=false},
        {name='! menu 4', enable=false}
    },
    listeners = {}
}

function Model:new ()
    o = Model
    setmetatable(o, self)
    return o
end

function Model:update(value)
    if (self.index+value <= #self.dataset and self.index+value > 0) then
        self.index = self.index+value
        print(self.index)
        -- [1] clear
        for k,v in ipairs(self.dataset) do
            self.dataset[k].enable = false
        end
        -- [2] set
        self.dataset[self.index].enable = true
        -- TODO: async
        for k,listener in pairs(self.listeners) do
            listener:update(self.dataset)
        end
    end
end

function Model:watch(listener)
    table.insert(self.listeners, listener)
end

-- ================== viewer ========================
Viewer = {
}

function Viewer:new()
    local v = Viewer
    setmetatable(v, self)
    return v
end

function Viewer:update(dataset)
    os.execute("clear")
    local temp_buff = nil
    for k,v in pairs(dataset) do
        if v.enable then
            temp_buff = string.gsub(v.name, "!", "*")
        else
            temp_buff = string.gsub(v.name, "!", " ")
        end
        print(temp_buff)
    end
end

-- ================== Controller ====================
Controller = {
    model = Model:new(),
    viewer = Viewer:new(),
}

function Controller:new()
    local c = Controller
    setmetatable(c, self)
    self.model:watch(self.viewer)
    return c
end

function Controller:run()
    while true do
        local a = io.read()
        if a == "j" then
            self.model:update(1)
        elseif a == "k" then
            self.model:update(-1)
        else
            break
        end
    end
end

local controler = Controller:new()
controler:run()
